package cz.muni.fi.pa165.machineryrental.weblayer.controllers;

import cz.muni.fi.pa165.machineryrental.dto.CustomerDTO;
import cz.muni.fi.pa165.machineryrental.dto.RentalDTO;
import cz.muni.fi.pa165.machineryrental.service.CustomerService;
import cz.muni.fi.pa165.machineryrental.service.RentalService;
import cz.muni.fi.pa165.machineryrental.weblayer.utils.Utils;
import cz.muni.fi.pa165.machineryrental.weblayer.validator.CustomerValidator;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.InitBinder;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;

/**
 *
 * @author jostri
 */
@Controller
public class CustomerController {

    private static final Logger logger = Logger.getLogger(CustomerController.class.getName());
    @Autowired
    private CustomerService customerService;
    @Autowired
    private RentalService rentalService;
    @Autowired
    CustomerValidator customerValidator;

    @InitBinder
    public void initBinder(WebDataBinder webDataBinder) {
        SimpleDateFormat sf = Utils.getCurrentSimpleDateFormat();
        webDataBinder.registerCustomEditor(Date.class, new CustomDateEditor(sf, true));
        webDataBinder.setValidator(this.customerValidator);
    }

    @RequestMapping("/customer/index")
    public ModelAndView index() {

        List<CustomerDTO> customers = customerService.findAll();

        Map<String, Object> model = new HashMap<String, Object>();
        model.put("customers", customers);

        if (logger.isDebugEnabled()) {
            logger.debug(customers.size() + " customers retrieved");
        }

        return new ModelAndView("/customer/index.jsp", "model", model);
    }

    @RequestMapping(value = "/customer/index", method = RequestMethod.POST)
    public ModelAndView index(String searchBy, String search, Map<String, Object> map,
            HttpServletRequest request) {

        Map<String, Object> model = new HashMap<String, Object>();
        List<CustomerDTO> customers = new ArrayList<CustomerDTO>();

        if (searchBy != null && !searchBy.equals("")) {
            if (searchBy.equals("lastName")) {
                customers = customerService.findByLastName(search);
            } else if (searchBy.equals("email")) {
                customers.add(customerService.findByEmail(search));
            } else if (searchBy.equals("companyNumber")) {
                customers.add(customerService.findByCompanyNumber(search));
            }
        }

        model.put("customers", customers);
        model.put("search", search);
        model.put("searchBy", searchBy);

        if (logger.isDebugEnabled()) {
            logger.debug(customers.size() + " customers retrieved after searching by: " + searchBy + " and search phrase: " + search);
        }

        return new ModelAndView("/customer/index.jsp", "model", model);
    }

    @RequestMapping("/customer/detail/{id}")
    public ModelAndView detail(@PathVariable long id) {

        Map<String, Object> model = new HashMap<String, Object>();

        CustomerDTO customer = this.customerService.getById(id);
        if (customer == null) {
            model.put("customer", null);
        } else {
            List<RentalDTO> rentals = this.rentalService.findByCustomer(customer);
            model.put("customer", customer);
            model.put("rentals", rentals);
        }

        if (logger.isDebugEnabled()) {
            logger.debug("Customer " + customer + " retrieved");
        }

        return new ModelAndView("/customer/detail.jsp", "model", model);
    }

    @RequestMapping("/customer/add")
    public ModelAndView add() {
        return new ModelAndView("/customer/add.jsp", "customer", new CustomerDTO());
    }

    @RequestMapping(value = "/customer/add", method = RequestMethod.POST)
    public ModelAndView add(@Valid @ModelAttribute("customer") CustomerDTO customer, BindingResult result) {

        if (result.hasErrors()) {
            return new ModelAndView("/customer/add.jsp");
        }

        this.customerService.create(customer);

        if (logger.isDebugEnabled()) {
            logger.debug("New customer: " + customer + " was added");
        }

        ModelAndView mav = new ModelAndView();
        mav.setViewName("redirect:/customer/detail/" + customer.getId());
        return mav;
    }

    @RequestMapping(value = "/customer/edit/{id}", method = RequestMethod.GET)
    public ModelAndView edit(@PathVariable long id) {

        CustomerDTO customer = customerService.getById(id);

        return new ModelAndView("/customer/edit.jsp", "customer", customer);
    }

    @RequestMapping(value = "/customer/edit", method = RequestMethod.POST)
    public ModelAndView edit(@Valid @ModelAttribute("customer") CustomerDTO customer, BindingResult result) {

        if (result.hasErrors()) {
            return new ModelAndView("/customer/edit.jsp", "customer", customer);
        }

        this.customerService.update(customer);

        if (logger.isDebugEnabled()) {
            logger.debug("Customer with ID " + customer.getId() + " was edited");
        }

        return new ModelAndView("redirect:/customer/detail/" + customer.getId());
    }

    @Secured("ROLE_ADMIN")
    @RequestMapping("/customer/remove/{id}")    
    public ModelAndView remove(@PathVariable long id) {

        CustomerDTO customer = this.customerService.getById(id);
        customerService.remove(customer);
        return new ModelAndView("redirect:/customer/index");
    }
}
